<template>
  <div class="fast-table-container">
    <el-table
        ref="table"
        :loading="options.loading"
        :cell-style="options.tableStyle?.cellStyle"
        :header-cell-style="options.tableStyle?.headerCellStyle"

        :height="options.height"
        :max-height="options.maxHeight"
        :show-header="options.showHeader"
        :stripe="options.stripe"
        :border="options.border"
        :size="options.size"
        :data="data"
        :highlight-current-row="options.highlightCurrentRow"
        :row-key="options.rowKey"
        @row-click="handleRowClick"
        @current-change="handleCurrentChange"
        @selection-change="handleSelectionChange"
        @sort-change="handleSortChange"
    >
      <!--当数据为空时自定义的内容-->
      <template #empty>
        <EmptyData v-if="!data || data.length == 0"/>
      </template>


      <!--多选列-->
      <el-table-column
          v-if="options.selection"
          type="selection"
          :reserve-selection="options.reserveSelection"
          width="40"
      />

      <!--索引列-->
      <el-table-column v-if="options.index" type="index" width="60" :label="$t('other.index')"/>
      <!--主键列-->
      <el-table-column v-if="options.primaryKey" prop="id" header-align="center" :label="$t('common.id')" min-width="180" show-overflow-tooltip>
        <template #default="scope">
          {{ scope.row.id }}
          <SvgIcon name="ele-CopyDocument" class="icon_copy" @click="copyText(scope.row.id)" />
        </template>
      </el-table-column>

      <template v-for="(col, index) in options.columns" :key="index">
        <!--操作列-->
        <template v-if="col.action">
          <!-- 操作列-插槽 -->
          <slot v-if="col.action.slot" :name="col.action.slot" :key="index"/>

          <!--操作列-展示列-->
          <el-table-column
              v-else
              :width="col.width"
              :fixed="col.fixed"
              :label="col.label || $t('common.action')"
              :align="col.align"
              :header-align="col.headerAlign"
          >
            <template #default="scope">
              <!--display参数为dropdown将以下拉方式展示，默认为tile平铺展示-->
              <template v-if="col.action.display == 'dropdown'">
                <el-dropdown placement="bottom">
                  <img
                      src="/@/assets/common/ic_operation.svg"
                      alt=""
                      style="cursor: pointer;"
                  />

                  <template #dropdown>
                    <el-dropdown-menu style="white-space: nowrap !important;">
                      <el-dropdown-item
                          v-for="(item, index) in col.action.buttons" :key="index"
                          v-auth="item.auth"
                          :disabled="typeof item.disabled === 'function' ? item.disabled(scope.row) : item.disabled"
                          @click.native="item.click(scope.row)">
                        {{ typeof item.label === 'function' ? item.label(scope.row) : item.label }}
                      </el-dropdown-item>
                    </el-dropdown-menu>
                  </template>
                </el-dropdown>
              </template>
              <template v-else>
                <el-button v-for="(item, index) in col.action.buttons" :key="index"
                           text
                           type="primary"
                           :icon="item.icon"
                           v-auth="item.auth"
                           :disabled="typeof item.disabled === 'function' ? item.disabled(scope.row) : item.disabled"
                           @click="item.click(scope.row)"
                >
                {{ typeof item.label === 'function' ? item.label(scope.row) : item.label }}
                </el-button>
              </template>
            </template>
          </el-table-column>
        </template>

        <!--创建信息-->
        <el-table-column v-else-if="col.createInfo" header-align="center" min-width="150" :label="$t('common.createInfo')">
          <template #default="scope">
            <div>{{ scope.row.createBy }}</div>
            <div>{{ scope.row.createTime }}</div>
          </template>
        </el-table-column>
        <!--更新信息-->
        <el-table-column v-else-if="col.updateInfo"  header-align="center" min-width="150" :label="$t('common.updateInfo')">
          <template #default="scope">
            <div>{{ scope.row.updateBy }}</div>
            <div>{{ scope.row.updateTime }}</div>
          </template>
        </el-table-column>

        <!-- 普通列 -->
        <el-table-column
            v-else
            :key="index"
            :prop="col.prop"
            :label="col.label"
            :width="col.width"
            :min-width="col.minWidth ? col.minWidth : ''"
            :fixed="col.fixed"
            :sortable="col.sortable || 'custom'"
            :show-overflow-tooltip="col.showOverflowTooltip || true"
            :render-header="col.renderHeader"
            :formatter="col.formatter"
        >
          <template #default="scope">
            <!--switch组件-->
            <el-switch v-if="col.switch"
                :value="scope.row[col.prop]"
                :active-value="col.switch.activeValue"
                :inactive-value="col.switch.inactiveValue"
                @click.native="col.switch.change ? col.switch.change(scope.row) : ''"
            />
            <!--字典组件-->
            <dict-tag v-if="col.dictTag" :options="col.dictTag" :value="scope.row[col.prop]"/>
          </template>

        </el-table-column>
      </template>
    </el-table>
  </div>
</template>
<script setup lang="ts">
import {PropType} from "vue";
import EmptyData from "/@/components/biz/empty-data.vue";
import {TableStyle} from "/@/hooks/table";
import commonFunction from "/@/utils/commonFunction";

const { copyText } = commonFunction();

// 表格配置项
export interface FastTableOptions {
  // 是否加载中
  loading?: boolean,
  // 表格样式
  tableStyle?: TableStyle,

  // table 的最大高度。 合法的值为数字或者单位为 px 的高度。
  maxHeight?: string | number,
  // table 的高度。 默认为自动高度。 如果 height 为 number 类型，单位 px；如果 height 为 string 类型，则这个高度会设置为 Table 的 style.height 的值，Table 的高度会受控于外部样式。
  height?: string | number,
  // 是否为斑马纹 table
  stripe?: boolean,
  // 是否带有纵向边框
  border?: boolean,
  // Table 的尺寸 -> '' | 'large' | 'default' | 'small'
  size?: string,

  // 是否显示表头
  showHeader?: boolean,
  // 是否要高亮当前行
  highlightCurrentRow?: boolean,

  // 行数据的 Key，用来优化 Table 的渲染； 在使用reserve-selection功能与显示树形数据时，该属性是必填的。 类型为 String 时，支持多层访问：user.info.id，但不支持 user.info[0].id，此种情况请使用 Function。
  rowKey?: string,

  // 是否需要索引列
  index?: boolean,
  // 是否需要主键列
  primaryKey?: boolean
  // 是否需要多选列
  selection?: boolean,

  // 数据刷新后是否保留选项，仅对  type=selection 的列有效， 请注意， 需指定 row-key 来让这个功能生效。
  reserveSelection?: boolean,

  // 表格数据列
  columns?: Array<FastTableColumns>,

  // 行点击事件
  rowClick?: Function,
  // 当表格的当前行发生变化的时候会触发该事件，如果要高亮当前行，请打开表格的 highlight-current-row 属性
  currentChange?: Function,
  // 当选择项发生变化时会触发该事件
  selectionChange?: Function,
  // 当用户对某一列进行排序时会触发该事件
  sortChange?: Function,
}

// 表格数据列
export interface FastTableColumns {
  // 列属性
  prop?: string,
  // 列标题
  label?: string,
  // 列宽度
  width?: string,
  // 最小宽度
  minWidth?: string,
  // 固定列
  fixed?: string,
  // 对齐方式 'left' | 'center' | 'right'
  align?: string,
  // 表头对齐方式， 若不设置该项，则使用表格的对齐方式
  headerAlign?: string,
  // 对应列是否可以排序， 如果设置为 'custom'，则代表用户希望远程排序，需要监听 Table 的 sort-change 事件
  sortable?: boolean | string,
  // 当内容过长被隐藏时显示 tooltip
  showOverflowTooltip?: boolean,
  // 表头单元格渲染方法
  renderHeader?: Function,
  // 列内容渲染方法
  formatter?: Function,

  // switch组件
  switch?: {
    // switch组件激活值
    activeValue: string | Function,
    // switch组件非激活值
    inactiveValue: string | Function,
    // switch组件点击事件
    change: Function,
  },
  // 字典标签
  dictTag?: Array<any>,

  // 创建信息
  createInfo?: boolean,
  // 更新信息
  updateInfo?: boolean,

  // 操作列
  action?: FastTableActionColumnsAction,
}

// 操作列
export interface FastTableActionColumnsAction {
  // 操作列插槽
  slot?: string,
  // 操作列展示方式：tile 平铺展示，dropdown 下拉展示
  display?: string | 'tile' | 'dropdown',
  // 操作列按钮
  buttons?: Array<FastTableActionColumnsActionButton>,
}

// 操作列按钮
export interface FastTableActionColumnsActionButton {
  // 按钮文本
  label: string | Function,
  // 按钮权限
  auth?: string,
  // 按钮点击事件
  click: Function,
  // 按钮是否禁用
  disabled?: boolean | Function,
  // 按钮图标
  icon?: string,
}


const emits = defineEmits(['currentChange', 'selectionChange', 'sortChange']);

const props = defineProps({
  // 配置项
  options: {
    type: Object as PropType<FastTableOptions>,
    required: true,
  },
  // 数据
  data: {
    type: Array<any>,
    default: () => []
  }
})

const defaultOptions = {
  loading: false,
  maxHeight: '100%',
  height: '100%',
  stripe: true,
  border: true,
  size: 'default',
  showHeader: true,
  highlightCurrentRow: false,
  rowKey: 'id',
  index: false,
  primaryKey: true,
  selection: true,
  reserveSelection: true,
}

// 表格实例
const table = ref()

onMounted(() => {
  // console.log('fast-table onMounted', props.options)
  // Object.assign(defaultOptions, props.options)
  mergeDefaultOptions(defaultOptions, props.options)
})

/**
 * 合并默认属性配置和自定义属性配置
 * @param options 默认属性配置对象
 * @param props 自定义属性配置对象
 * @returns 合并后的属性配置对象
 */
const mergeDefaultOptions = (options: any, props: any): FastTableOptions => {
  for (const key in options) {
    if (!Object.getOwnPropertyDescriptor(props, key)) {
      props[key] = options[key];
    }
  }
  return props;
};

// 处理当前选中行变化事件
const handleCurrentChange = (currentRow: any, oldCurrentRow: any) => {
  // console.log('handleCurrentChange', currentRow, oldCurrentRow)
  emits('currentChange', currentRow)

  if (props.options.currentChange) {
    props.options.currentChange(currentRow, oldCurrentRow)
  }
}
// 处理多选变化事件
const handleSelectionChange = (rows: any) => {
  // console.log('handleSelectionChange', rows)
  emits('selectionChange', rows)
  if (props.options.selectionChange) {
    props.options.selectionChange(rows)
  }
}
// 处理行点击事件
const handleRowClick = (row: any) => {
  if (props.options.rowClick) {
    props.options.rowClick(row)
  }
}
// 处理排序变化事件
const handleSortChange = (rows: any) => {
  // console.log('handleSortChange', rows)
  emits('sortChange', rows)
  if (props.options.sortChange) {
    props.options.sortChange(rows)
  }
}

// 暴露变量
defineExpose({
  table
})
</script>


<style scoped lang="scss">
.fast-table-container {

}
</style>
